package ferp.core.game;

import ferp.core.log.Log;
import ferp.core.player.AI;

/**
 * User: olegs
 * Date: 3/27/13 11:48 AM
 */
public abstract class Confirmation
{
  public static final Confirmation play = new Confirmation()
  {
    @Override
    public boolean isRequired(Settings.Confirmation confirmation, Game game, Settings settings, Bid bid)
    {
      return game.rounds == 0 && super.isRequired(confirmation, game, settings, bid);
    }

    @Override
    protected boolean isValid(Game game, Settings settings, Bid bid)
    {
      Bid estimated = getEstimatedBid(game, settings);
      int index = bid.tricks - 6;

      return 0 <= index && index < deltas.length && (estimated.tricks >= bid.tricks || bid.tricks - estimated.tricks <= deltas[index]);
    }

    private final int deltas[] = {2, 1, 0};
  };

  public static final Confirmation pass = new Confirmation()
  {
    @Override
    public boolean isRequired(Settings.Confirmation confirmation, Game game, Settings settings, Bid bid)
    {
      return game.rounds == 0 && super.isRequired(confirmation, game, settings, bid);
    }

    @Override
    protected boolean isValid(Game game, Settings settings, Bid bid)
    {
      Bid estimated = getEstimatedBid(game, settings);
      Bid min = game.options.bid;
      int index = min.tricks - 6;

      return 0 <= index && index < deltas.length && min.tricks - estimated.tricks > deltas[index];
    }

    private final int deltas[] = {2, 1, 0};
  };

  public static final Confirmation misere = new Confirmation()
  {
    @Override
    public boolean isRequired(Settings.Confirmation confirmation, Game game, Settings settings, Bid bid)
    {
      return game.rounds == 0 && super.isRequired(confirmation, game, settings, bid);
    }

    @Override
    protected boolean isValid(Game game, Settings settings, Bid bid)
    {
      return getEstimatedBid(game, settings).isMisere();
    }
  };

  public static final Confirmation without3 = new Confirmation()
  {
    @Override
    protected boolean isValid(Game game, Settings settings, Bid bid)
    {
      Bid estimated = getEstimatedContract(game);
      Bid min = game.getBid(0).current;

      return min.tricks - estimated.tricks > 1;
    }
  };

  public static final Confirmation contract = new Confirmation()
  {
    @Override
    public boolean isRequired(Settings.Confirmation confirmation, Game game, Settings settings, Bid bid)
    {
      return game.hand == 0 && super.isRequired(confirmation, game, settings, bid);
    }

    @Override
    protected boolean isValid(Game game, Settings settings, Bid bid)
    {
      Bid estimated = getEstimatedContract(game);

      return bid.equals(estimated);
    }
  };

  public boolean isRequired(Settings.Confirmation confirmation, Game game, Settings settings, Bid bid)
  {
    return confirmation == Settings.Confirmation.ALWAYS ||
          (confirmation == Settings.Confirmation.INTELLIGENT && !isValid(game, settings, bid));
  }

  protected abstract boolean isValid(Game game, Settings settings, Bid bid);

  private static Bid getEstimatedBid(Game game, Settings settings)
  {
    // bad way to get the strategy
    Bid bid = ((AI)game.player(1)).strategy().bidding().bid(game, settings, game.player(0), game.options.bid);

    Log.debug(Log.TAG, "estimated player bid: " + bid);

    return bid;
  }

  private static Bid getEstimatedContract(Game game)
  {
    // bad way to get the strategy
    Bid bid = ((AI)game.player(1)).strategy().contracting().tricks(game.getHand(game.human().id()).current, game.human().isFirstHand(game));

    Log.debug(Log.TAG, "estimated player contract: " + bid);

    return bid;
  }
}
